package com.godofball.todo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.godofball.todo.contants.SystemConstants;
import com.godofball.todo.entity.utils.AppHttpCodeEnum;
import com.godofball.todo.entity.utils.ResponseResult;
import com.godofball.todo.entity.vo.DoneTaskVo;
import com.godofball.todo.entity.vo.PageVo;
import com.godofball.todo.entity.vo.WorkTaskVo;
import com.godofball.todo.mapper.TaskMapper;
import com.godofball.todo.entity.Task;
import com.godofball.todo.service.TaskService;
import com.godofball.todo.utils.BaseContext;
import com.godofball.todo.utils.BeanCopyUtils;
import com.godofball.todo.utils.DateUtils;
import com.godofball.todo.utils.TaskUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;


import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 任务表(Task)表服务实现类
 *
 * @author makejava
 * @since 2023-12-31 16:36:58
 */
@Service("taskService")
@Slf4j
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {

    @Override
    public ResponseResult selectWorkTask(Integer pageNum, Integer pageSize, String title, String type) {

        String username = BaseContext.getCurrentUser();

        LambdaQueryWrapper<Task> taskLambdaQueryWrapper = new LambdaQueryWrapper<>();
        taskLambdaQueryWrapper.eq(Task::getCreateUsername, username);
        taskLambdaQueryWrapper.like(StringUtils.hasLength(title), Task::getTitle, title);
        taskLambdaQueryWrapper.like(StringUtils.hasLength(title), Task::getContent, title);
        taskLambdaQueryWrapper.like(StringUtils.hasLength(type), Task::getType, type);

        taskLambdaQueryWrapper.in(Task::getState,
                SystemConstants.TASK_NOT_START,
                SystemConstants.TASK_OVERDUE,
                SystemConstants.TASK_STARTED);

//        taskLambdaQueryWrapper.and(wrapper->{
//           wrapper.in
//        });

        Page<Task> taskPage = new Page<>(pageNum, pageSize);

        this.page(taskPage, taskLambdaQueryWrapper);

        List<Task> taskList = taskPage.getRecords();


        //更新task的状态
        taskList.forEach(
                task -> {
                    String oldState = task.getState();
                    String newState = TaskUtil.getWorkTaskStatus(task.getStartTime(), task.getEndTime());

                    if (!oldState.equals(newState)){
                        task.setState(newState);
                        this.updateById(task);
                    }
                });

        List<WorkTaskVo> workTaskVos = BeanCopyUtils.copyBeanList(taskList, WorkTaskVo.class);

        PageVo pageVo = new PageVo();
        pageVo.setRows(workTaskVos);
        pageVo.setTotal((int) taskPage.getTotal());

        return ResponseResult.okResult(pageVo);

    }

    @Override
    public ResponseResult addTask(Task task) {
        task.setId(null);
        task.setCompleteTime(null);
        task.setIsDelete(0);

        Date startTime = task.getStartTime();
        Date endTime = task.getEndTime();
        if (startTime==null||endTime==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.REQUIRE_TIME);
        }

        LambdaQueryWrapper<Task> taskLambdaQueryWrapper = new LambdaQueryWrapper<>();
        taskLambdaQueryWrapper.eq(Task::getCreateUsername,BaseContext.getCurrentUser());
        taskLambdaQueryWrapper.eq(StringUtils.hasLength(task.getTitle()),Task::getTitle,task.getTitle());
        taskLambdaQueryWrapper.isNull(Task::getCompleteTime);
        Task one = this.getOne(taskLambdaQueryWrapper);
        if (one!=null){
            return ResponseResult.errorResult(AppHttpCodeEnum.TASK_TITLE_EXIST);
        }

        String status = TaskUtil.getWorkTaskStatus(task.getStartTime(), task.getEndTime());
        task.setState(status);


        this.save(task);
        return ResponseResult.okResult("任务添加成功");
    }

    @Override
    public ResponseResult deleteTask(String id) {
        Task task = this.getById(id);
        if (task == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.TASK_NO_EXIST);
        }

        String createUsername = task.getCreateUsername();
        String username = BaseContext.getCurrentUser();
        if (!createUsername.equals(username)){
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }

        log.info(task.toString());
        //已完成的任务不能删
        if (TaskUtil.isWorkTask(task.getState())) {
            this.removeById(id);
        } else {
            return ResponseResult.errorResult(404, "任务删除失败");
        }
        return ResponseResult.okResult("任务删除成功");
    }

    @Override
    public ResponseResult updateTask(Task task) {
        Task oldTask = this.getById(task.getId());
        if (oldTask == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.TASK_NO_EXIST);
        }

        String createUsername = oldTask.getCreateUsername();
        String username = BaseContext.getCurrentUser();
        if (!createUsername.equals(username)){
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }

//        oldTask.setTitle(task.getTitle());
        oldTask.setContent(task.getContent());
        oldTask.setType(task.getType());
        oldTask.setRemark(task.getRemark());
        oldTask.setStartTime(task.getStartTime());
        oldTask.setEndTime(task.getEndTime());

        String status = TaskUtil.getWorkTaskStatus(task.getStartTime(), task.getEndTime());
        oldTask.setState(status);

        this.updateById(oldTask);

        return ResponseResult.okResult("任务信息修改成功");
    }

    @Override
    public ResponseResult submitTask(String id) {
        Task task = this.getById(id);
        if (task == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.TASK_NO_EXIST);
        }

        String createUsername = task.getCreateUsername();
        String username = BaseContext.getCurrentUser();
        if (!createUsername.equals(username)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }

        if (!TaskUtil.isWorkTask(task.getState())) {
            return ResponseResult.errorResult(501, "任务已完成，不能再次提交");
        }

        //获取任务完成状态
        Date completeTime = new Date();
        String status = TaskUtil.getDoneTaskStatus(task.getStartTime(), task.getEndTime(), completeTime);

        task.setState(status);
        task.setCompleteTime(completeTime);

        this.updateById(task);

        return ResponseResult.okResult("任务提交成功");
    }

    @Override
    public ResponseResult selectDoneTask(Integer pageNum, Integer pageSize, String title, String content, String type) {
        String username = BaseContext.getCurrentUser();

        LambdaQueryWrapper<Task> taskLambdaQueryWrapper = new LambdaQueryWrapper<>();
        taskLambdaQueryWrapper.eq(Task::getCreateUsername, username);
        taskLambdaQueryWrapper.like(StringUtils.hasLength(title), Task::getTitle, title);
        taskLambdaQueryWrapper.like(StringUtils.hasLength(content), Task::getContent, content);
        taskLambdaQueryWrapper.like(StringUtils.hasLength(type), Task::getType, type);

        taskLambdaQueryWrapper.in(Task::getState,
                SystemConstants.TASK_COMPLETE_AHEAD,
                SystemConstants.TASK_COMPLETE_NORMAL,
                SystemConstants.TASK_COMPLETE_OVERDUE);

        Page<Task> taskPage = new Page<>(pageNum, pageSize);

        this.page(taskPage, taskLambdaQueryWrapper);

        List<Task> taskList = taskPage.getRecords();


        List<DoneTaskVo> doneTaskVos = BeanCopyUtils.copyBeanList(taskList, DoneTaskVo.class);

        PageVo pageVo = new PageVo();
        pageVo.setRows(doneTaskVos);
        pageVo.setTotal((int) taskPage.getTotal());

        return ResponseResult.okResult(pageVo);
    }

    @Override
    public ResponseResult selectTaskNumber() {
        String username = BaseContext.getCurrentUser();
        LambdaQueryWrapper<Task> taskLambdaQueryWrapper = new LambdaQueryWrapper<>();
        taskLambdaQueryWrapper.eq(Task::getCreateUsername, username);

        List<Task> taskList = this.list(taskLambdaQueryWrapper);

        HashMap<String, Integer> map = new HashMap<>();


        Integer notStart = 0;
        Integer started = 0;
        Integer overdue = 0;
        Integer completed = 0;

        for (Task task : taskList) {
            String state = task.getState();
            if (SystemConstants.TASK_NOT_START.equals(state)) {
                notStart++;
            } else if (SystemConstants.TASK_STARTED.equals(state)) {
                started++;
            } else if (SystemConstants.TASK_OVERDUE.equals(state)) {
                overdue++;
            } else {
                completed++;
            }
        }

        map.put("notStart", notStart);
        map.put("started", started);
        map.put("overdue", overdue);
        map.put("completed", completed);

        return ResponseResult.okResult(map);
    }

    @Override
    public ResponseResult selectTaskByTime() {
        String username = BaseContext.getCurrentUser();

        LambdaQueryWrapper<Task> taskLambdaQueryWrapper = new LambdaQueryWrapper<>();
        taskLambdaQueryWrapper.eq(Task::getCreateUsername, username);
        List<Task> taskList = this.list(taskLambdaQueryWrapper);

        HashMap<String, Integer> map = new LinkedHashMap<>();
        map.put(SystemConstants.TASK_STARTED, 0);
        map.put(SystemConstants.TASK_NOT_START, 0);
        map.put(SystemConstants.TASK_OVERDUE, 0);
        map.put(SystemConstants.TASK_COMPLETE_NORMAL, 0);
        map.put(SystemConstants.TASK_COMPLETE_AHEAD, 0);
        map.put(SystemConstants.TASK_COMPLETE_OVERDUE, 0);
        for (Task task : taskList) {
            String state = task.getState();
            Integer count = map.getOrDefault(state, 0);
            map.put(state, count + 1);
        }

        ArrayList<Map> outter = new ArrayList<>();

        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            HashMap<Object, Object> obj = new HashMap<>();
            obj.put("name", entry.getKey());
            obj.put("value", entry.getValue());
            outter.add(obj);
        }


        ArrayList<Map> inner = new ArrayList<>();
        Integer workTaskNum =
                map.getOrDefault(SystemConstants.TASK_NOT_START, 0)
                        + map.getOrDefault(SystemConstants.TASK_OVERDUE, 0)
                        + map.getOrDefault(SystemConstants.TASK_STARTED, 0);

        Integer doneTaskNum =
                map.getOrDefault(SystemConstants.TASK_COMPLETE_OVERDUE, 0)
                        + map.getOrDefault(SystemConstants.TASK_COMPLETE_AHEAD, 0)
                        + map.getOrDefault(SystemConstants.TASK_COMPLETE_NORMAL, 0);



        HashMap<Object, Object> obj = new HashMap<>();
        obj.put("name", SystemConstants.TASK_NOT_DONE);
        obj.put("value", workTaskNum);
        inner.add(obj);


        obj = new HashMap<>();
        obj.put("name", SystemConstants.TASK_HAVE_DONE);
        obj.put("value", doneTaskNum);
        inner.add(obj);

        ArrayList<Object> legend = new ArrayList<>();
        legend.add(SystemConstants.TASK_OVERDUE);
        legend.add(SystemConstants.TASK_STARTED);
        legend.add(SystemConstants.TASK_NOT_START);
        legend.add(SystemConstants.TASK_COMPLETE_NORMAL);
        legend.add(SystemConstants.TASK_COMPLETE_OVERDUE);
        legend.add(SystemConstants.TASK_COMPLETE_AHEAD);

        HashMap<Object, Object> mapVo = new HashMap<>();
        mapVo.put("outer", outter);
        mapVo.put("inner", inner);
        mapVo.put("legend", legend);

        return ResponseResult.okResult(mapVo);
    }

    @Override
    public ResponseResult selectTaskByWeek() {
        String username = BaseContext.getCurrentUser();

//        Date now = new Date();
        LocalDate now = LocalDate.now();
        Date thisWeekMonday = DateUtils.getStartDayOfWeek(now);
        System.out.println(thisWeekMonday);
        Date nextWeekMonday = DateUtils.getNextWeekMonday(thisWeekMonday);
        System.out.println(nextWeekMonday);
        LambdaQueryWrapper<Task> taskLambdaQueryWrapper = new LambdaQueryWrapper<>();
        taskLambdaQueryWrapper.eq(Task::getCreateUsername, username);
        taskLambdaQueryWrapper.ge(Task::getCreateTime, thisWeekMonday);
        taskLambdaQueryWrapper.lt(Task::getCreateTime, nextWeekMonday);

        List<Task> taskList = this.list(taskLambdaQueryWrapper);

        LinkedHashMap<Integer, Integer> map = new LinkedHashMap<>();
        for (int i = 0; i < 7; i++) {
            map.put(i, 0);
        }

        taskList.forEach(task -> {
            Date createTime = task.getCreateTime();
            int days = DateUtils.differentDays(thisWeekMonday, createTime);
            map.put(days, map.get(days) + 1);
        });

        return ResponseResult.okResult(map.values());
    }
}

